/*+*********************************************************
Filename: spi_gateway\src\top.v
Description:
  transfer spi data on ethernet. Modified based on 04_eth_04.

Modification:
2024.03.14 creation by H.Zheng (04_eth_04)
2024.03.20 change udp payload (mic sample data) from big-endian to little-endian,
           16bit with 2 channel(same data).
2024.04.16 change ip&mac addr as parameter, change UART_FRE to 500k
2024.09.22 change data source from mic to spi (spi_gateway)
2024.09.28 trigger data writing to ety fifo by received 32 bit data
2024.09.30 change uart tx to simpleuart_tx32

**********************************************************-*/

module top(
	input                        clk,
	input                        rst_n,
	input                        uart_rx,
	output                       uart_tx,
    output wire [5:0] led, 
    output wire ety_phyrst,
    input netrmii_clk50m,
    input netrmii_rx_crs,
    output netrmii_mdc,
    output netrmii_txen,
    inout netrmii_mdio,
    output [1:0] netrmii_txd,
    input [1:0] netrmii_rxd,
    input wire gw_ws63_cs_n,
    input wire gw_ws63_clk,
    input wire gw_ws63_data_out

);

	parameter DEST_MAC_ADDR = 48'hff_ff_ff_ff_ff_ff; 
	parameter SRC_MAC_ADDR = {8'h06, 8'h00, 8'haa, 8'hbb, 8'h0c, 8'hdd}; 
	parameter DEST_IP_ADDR = {8'd192,8'd168,8'd15,8'd15}; 
	parameter SRC_IP_ADDR = {8'd192,8'd168,8'd15,8'd14}; 
	parameter DEST_UDP_PORT = 16'd5678; 
	parameter SRC_UDP_PORT = 16'd1234;


//assign led = 6'b111001;


/**
 * clock section
 */
wire clk1m;
wire clk6m;
PLL_6M PLL6m(
    .clkout(clk6m),
    .clkoutd(clk1m),
    .clkin(clk)
);

  /**
   * ety section
   */
  wire [31:0] udp_data;
  wire udp_data_clk;


  ety#(.DEST_MAC_ADDR(DEST_MAC_ADDR),	.SRC_MAC_ADDR(SRC_MAC_ADDR), 
       .DEST_IP_ADDR(DEST_IP_ADDR), .SRC_IP_ADDR(SRC_IP_ADDR),
       .DEST_UDP_PORT(DEST_UDP_PORT), .SRC_UDP_PORT(SRC_UDP_PORT)) m_ety(
    .clk1m(clk1m), 
    .rst_n(rst_n),
    .ety_phyrst(ety_phyrst),
    .netrmii_clk50m(netrmii_clk50m),
    .netrmii_rx_crs(netrmii_rx_crs),
    .netrmii_mdc(netrmii_mdc),
    .netrmii_txen(netrmii_txen),
    .netrmii_mdio(netrmii_mdio),
    .netrmii_txd(netrmii_txd),
    .netrmii_rxd(netrmii_rxd),
    .data(udp_data),
    .data_clk(udp_data_clk)
  );


/**
 * uart section
 */

wire[31:0] tx_data;
wire tx_data_valid;
wire tx_data_ready;

simpleuart_tx32 m_uart_tx(
	.clk(clk),
	.resetn(rst_n),
  .ser_tx(uart_tx),
  .reg_dat_we(tx_data_valid),
	.reg_dat_di(tx_data)
);

/**
 * spi part
 */
//shift data in
  reg [31:0] gw_shift_reg;
  reg [31:0] data_reg;

  reg [4:0] bit_counter;
  always @(posedge gw_ws63_clk or negedge rst_n) begin
//  always @(negedge gw_ws63_clk or negedge rst_n) begin
    if (!rst_n) begin
      gw_shift_reg <= 32'd0;
      bit_counter <= 5'b0;
    end
//    else if (!gw_ws63_cs_n)
    else begin
      gw_shift_reg <= {gw_shift_reg[30:0], gw_ws63_data_out};	
      bit_counter <= bit_counter + 1'b1;
    end
  end	


  wire is_bit_counter_zero = (bit_counter == 5'b0) ? 1'b1 : 1'b0;

//get delay posedge of is_bit_counter_zero
  reg [2:0] counter_zero_edge;
  always @(negedge clk) begin
    counter_zero_edge <= {counter_zero_edge[1:0], is_bit_counter_zero};	
  end

  wire counter_zero_posedge_delay1 = (~counter_zero_edge[1]) & counter_zero_edge[0]; 
  wire counter_zero_posedge_delay2 = (~counter_zero_edge[2]) & counter_zero_edge[1]; 

  //trigger data transfer every recieved 32bit
  always @(posedge counter_zero_posedge_delay1) begin
    data_reg <= gw_shift_reg;
  end	

//uart tx data and trigger signal
assign tx_data = data_reg;

//assign tx_data_valid = counter_zero_posedge_delay2;

/*
//update data_reg via posedge of cs_n
  always @(posedge gw_ws63_cs_n) begin
    data_reg <= gw_shift_reg;
  end	
*/


//get delay posedge of gw_ws63_cs_n
  reg [2:0] cs_edge;
  always @(negedge clk) begin
    cs_edge <= {cs_edge[1:0], gw_ws63_cs_n};	
  end

  wire cs_posedge_delay1 = (~cs_edge[1]) & cs_edge[0]; 

  //trigger uart tx every cs up
  assign tx_data_valid = cs_posedge_delay1;


//
//udp-ety fifo write data
//
  //change data from big-indian to little-indian
  assign udp_data = {data_reg[23:16],data_reg[31:24],data_reg[7:0],data_reg[15:8]};
  //assign udp_data = data_reg;

//trigger ety fifo write
  //send data to ety fifo every 32bit received
  assign udp_data_clk = counter_zero_posedge_delay2;


/*
//debug: check cs

//count cs
  reg [20:0] cs_counter;
  always @(negedge gw_ws63_cs_n or negedge rst_n) begin
    if (!rst_n)
      cs_counter <= 1'd0;
    else
      cs_counter <= cs_counter+1;
  end	

  wire is_cs_counter_zero = (cs_counter[14:0] == 15'b0) ? 1'b1 : 1'b0;

//get delay posedge of is_bit_counter_zero
  reg [2:0] counter_zero_edge;
  always @(negedge clk) begin
    counter_zero_edge <= {counter_zero_edge[1:0], is_cs_counter_zero};	
  end

  wire counter_zero_posedge_delay1 = (~counter_zero_edge[1]) & counter_zero_edge[0]; 
  wire counter_zero_posedge_delay2 = (~counter_zero_edge[2]) & counter_zero_edge[1]; 

//uart signal
assign tx_data = data_reg;
//assign tx_data_valid = cs_posedge_delay1;
assign tx_data_valid = counter_zero_posedge_delay1;

*/

/**
 * led
 */
  wire[15:0] data_l={data_reg[15:0]};
  wire[14:0] l_amplitude = data_l[15] ? ((~data_l[14:0])+1'b1) : data_l[14:0];

  assign led = ~l_amplitude[14:9];

endmodule